package com.tender.desensitization.factory.field;

import com.tender.desensitization.FieldReflectUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ClassUtils;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.time.temporal.Temporal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.tender.desensitization.GlobalRequestResponseAdvice.circleMap;

@Slf4j
public class FieldAnnotationUserWrapperProcessFactory implements FieldAnnotationDetectionFactory {

    private FieldAnnotationDetectionFactoryFacade factoryFacade;

    /**
     * 不同的工厂，筛选不同的注解标注的 Field
     */
    public FieldAnnotationUserWrapperProcessFactory(FieldAnnotationDetectionFactoryFacade factoryFacade) {
        this.factoryFacade = factoryFacade;
    }

    public FieldAnnotationDetectionFactoryFacade getFactoryFacade() {
        return factoryFacade;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return !(Set.class.isAssignableFrom(clazz)
                || List.class.isAssignableFrom(clazz)
                || Map.class.isAssignableFrom(clazz)
                || ClassUtils.isPrimitiveOrWrapper(clazz)
                || Date.class == clazz
                || Temporal.class.isAssignableFrom(clazz)
                || clazz.isArray()
                || String.class == clazz);
    }

    @Override
    public boolean processType(Field param) {
        if (null == param) {
            return false;
        }
        // 处理用户自定义的包装类
        List<Field> allFields = FieldReflectUtils.getAllFields(param.getType());

        if (!CollectionUtils.isEmpty(allFields)) {
            List<Class<?>> classList = circleMap.get(TopClassContext.getTopClass());
            // 存在类型嵌套
            if (classList.contains(param.getType())) {
                return false;
            } else {
                classList.add(param.getType());
            }
        }

        for (Field field : allFields) {
            FieldAnnotationDetectionFactory processFactory = getFactoryFacade().getProcessFactory(field.getType());
            if (null != processFactory) {
                if (processFactory.processType(field)) {
                    return true;
                }
            }
        }
        return false;
    }

}